﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace YTCMS.Core.File
{
    public sealed class ImageHelper
    {
        #region 图片类型
        private static SortedDictionary<int, ImageType> filenameExtension;
        private static Dictionary<UpFileType, List<string>> upfileTypes;
        private static void InitImageExtension()
        {
            filenameExtension = new SortedDictionary<int, ImageType>();
            filenameExtension.Add((int)ImageType.BMP, ImageType.BMP);
            filenameExtension.Add((int)ImageType.JPG, ImageType.JPG);
            filenameExtension.Add((int)ImageType.GIF, ImageType.GIF);
            filenameExtension.Add((int)ImageType.PCX, ImageType.PCX);
            filenameExtension.Add((int)ImageType.PNG, ImageType.PNG);
            filenameExtension.Add((int)ImageType.PSD, ImageType.PSD);
            filenameExtension.Add((int)ImageType.RAS, ImageType.RAS);
            filenameExtension.Add((int)ImageType.SGI, ImageType.SGI);
            filenameExtension.Add((int)ImageType.TIFF, ImageType.TIFF);

        }

        private static void InitUpFileType()
        {
            upfileTypes = new Dictionary<UpFileType, List<string>>();
            upfileTypes.Add(UpFileType.image, ".gif,.jpg,.jpeg,.png,.bmp".Split(',').ToList());
            upfileTypes.Add(UpFileType.flash, ".swf,.flv".Split(',').ToList());
            upfileTypes.Add(UpFileType.media, ".swf,.flv,.mp3,.wav,.wma,.wmv,.mid,.avi,.mpg,.asf,.rm,.rmvb".Split(',').ToList());
            upfileTypes.Add(UpFileType.file, ".doc,.docx,.xls,.xlsx,.ppt,.htm,.html,.txt,.zip,.rar,.gz,.bz2".Split(',').ToList());
        }

        /// <summary>
        /// 获取图片文件后缀
        /// </summary>
        /// <param name="fileStream"></param>
        /// <returns></returns>
        public static string GetType(Stream fileStream)
        {
            return GetImageType(fileStream).ToString().ToLower();
        }

        /// <summary> 
        /// 通过文件头判断图像文件的类型 
        /// </summary> 
        /// <param name="fileStream">文件流</param> 
        /// <returns></returns> 
        public static ImageType GetImageType(Stream fileStream)
        {
            byte[] buffer = new byte[2];
            try
            {
                int total = fileStream.Read(buffer, 0, buffer.Length);
                if (total != buffer.Length)
                {
                    return ImageType.None;
                }
            }
            catch
            {
                return ImageType.None;
            }

            int key = (buffer[1] << 8) + buffer[0];
            ImageType type;
            if (filenameExtension.TryGetValue(key, out type))
            {
                return type;
            }
            return ImageType.None;
        }

        #endregion

        #region 图片尺寸

        /// <summary>
        /// 620*0
        /// </summary>
        public static ImageSize size600 = new ImageSize { Width = 600, Height = 0 };


        #endregion

        #region 水印参数

        public static WatermarkPms WarterTxt = new WatermarkPms()
        {
            type = WatermarkPms_Type.Txt,
            txt_pms = new WatermarkPms_Txt()
            {
                Text = "【隆金宝LONGKIN.NET】",
                Position = WatermarkPms_Position.Right_Bottom,
                FontSize = 14
            }
        };
        #endregion

        static ImageHelper()
        {
            InitImageExtension();
            InitUpFileType();
        }

        /// <summary>
        /// 获取指定大小的文件路径
        /// </summary>
        /// <param name="tempPath"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        public static string TempImg_GetSizePath(string fpath, ImageSize size)
        {
            if (string.IsNullOrWhiteSpace(fpath) || size == null)
                return "";
            var folder = Path.GetDirectoryName(fpath);
            var filename = Path.GetFileNameWithoutExtension(fpath);
            var extend = Path.GetExtension(fpath);
            var fullPath = Path.Combine(folder, size.GetFileName(filename, extend));
            if (!string.IsNullOrWhiteSpace(fullPath))
                fullPath = fullPath.Replace(@"https:\", @"https:\\").Replace(@"http:\", @"http:\\").Replace(@"\", @"/");
            return fullPath;
        }

        

        #region 下载
        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="serverfilpath"></param>
        /// <param name="filename"></param>
        /// <param name="hasExtend"></param>
        /// <param name="isWL"></param>
        public static bool Down_ToDownload(string serverfilpath, string filename = "", bool hasExtend = false, bool isWL = false, bool isEnd = true)
        {
            return Down_ToDownload2(serverfilpath, filename, hasExtend, isWL, isEnd, false);
        }

        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="serverfilpath"></param>
        /// <param name="filename"></param>
        /// <param name="hasExtend"></param>
        /// <param name="isWL"></param>
        public static bool Down_ToDownload2(string serverfilpath, string filename = "", bool hasExtend = false, bool isWL = false, bool isEnd = true, bool isReadOnly = true)
        {
            if (string.IsNullOrWhiteSpace(serverfilpath))
                return false;
            if (!isWL)
                serverfilpath = HttpContext.Current.Server.MapPath(serverfilpath);
            if (!System.IO.File.Exists(serverfilpath))
                return false;
            if (string.IsNullOrWhiteSpace(filename))
                filename = Path.GetFileName(serverfilpath);
            else
            {
                if (!hasExtend)
                    filename = filename + Path.GetExtension(serverfilpath);
            }
            string utfFileName = EncodeFileName(filename);
            //HttpUtility.UrlEncode(filename, System.Text.Encoding.UTF8);
            HttpContext.Current.Response.ContentType = "application/octet-stream";
            HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=\"" + utfFileName + "\";");
            ////attachment --- 作为附件下载  
            ////inline --- 在线打开  
            Down_DownLoadStreamFile2(serverfilpath, isReadOnly);
            //if (!isReadOnly)
            //{
            //    FileStream fileStream = new FileStream(serverfilpath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            //    long fileSize = fileStream.Length;
            //    HttpContext.Current.Response.AddHeader("Content-Length", fileSize.ToString());
            //    byte[] fileBuffer = new byte[fileSize];
            //    fileStream.Read(fileBuffer, 0, (int)fileSize);
            //    HttpContext.Current.Response.BinaryWrite(fileBuffer);
            //    fileStream.Close();
            //    //HttpContext.Current.Response.End();
            //}
            //else
            //{
            //    HttpContext.Current.Response.TransmitFile(serverfilpath);
            //}
            if (isEnd)
                HttpContext.Current.Response.End();
            //DownLoadStreamFile(serverfilpath);
            return true;
        }

        public static void Down_DownLoadStreamFile2(string serverfilpath, bool isOnlyRead = true)
        {
            System.IO.Stream iStream = null;
            // Buffer to read 10K bytes in chunk:
            int buffersize = 10000;
            byte[] buffer = new Byte[buffersize];
            // Length of the file:
            int length;
            // Total bytes to read:
            long dataToRead;
            // Identify the file name.
            string filename = System.IO.Path.GetFileName(serverfilpath);
            try
            {
                // Open the file.
                iStream = new System.IO.FileStream(serverfilpath, System.IO.FileMode.Open,
                System.IO.FileAccess.Read, isOnlyRead ? System.IO.FileShare.Read : FileShare.ReadWrite);
                // Total bytes to read:
                dataToRead = iStream.Length;
                //Response.ContentType = "application/octet-stream";
                //Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
                // Read the bytes.
                while (dataToRead > 0)
                {
                    // Verify that the client is connected.
                    if (HttpContext.Current.Response.IsClientConnected)
                    {
                        // Read the data in buffer.
                        length = iStream.Read(buffer, 0, buffersize);
                        // Write the data to the current output stream.
                        HttpContext.Current.Response.OutputStream.Write(buffer, 0, length);
                        // Flush the data to the HTML output.
                        HttpContext.Current.Response.Flush();
                        buffer = new Byte[buffersize];
                        dataToRead = dataToRead - length;
                    }
                    else
                    {
                        //prevent infinite loop if user disconnects
                        dataToRead = -1;
                    }
                }
            }
            catch (Exception ex)
            {
                // Trap the error, if any.
                //HttpContext.Current.Response.Write("Error : " + ex.Message);
            }
            finally
            {
                if (iStream != null)
                {
                    //Close the file.
                    iStream.Close();
                }
            }
        }

        /// <summary>
        /// 大文件传输
        /// </summary>
        /// <param name="serverfilpath"></param>
        public static void Down_DownLoadStreamFile(string serverfilpath)
        {
            int blocksize = 1024 * 100;
            byte[] buffer = new byte[blocksize];
            byte[] fileHeader = new byte[101];

            int startindex = 0;
            int bytesread = 0;
            int bytesfinish = 0;
            int filesize = 0;
            string headerText = string.Empty;
            BinaryReader bReader = null;

            bReader = new BinaryReader(System.IO.File.OpenRead(serverfilpath));
            filesize = Convert.ToInt32(bReader.BaseStream.Length);

            while (bytesfinish < filesize)
            {
                if (bytesfinish + blocksize < filesize)
                    bytesread = bReader.Read(buffer, startindex, blocksize);
                else
                    bytesread = bReader.Read(buffer, startindex, filesize - bytesfinish);

                bytesfinish += bytesread;
                HttpContext.Current.Response.OutputStream.Write(buffer, 0, bytesread);
            }
            bReader.Close();
            HttpContext.Current.Response.End();
        }

        /// <summary></summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static string EncodeFileName(string fileName)
        {
            string browser = HttpContext.Current.Request.Browser == null ? "" : HttpContext.Current.Request.Browser.Browser;
            //Firefox   Chrome  Safari
            if (!string.IsNullOrWhiteSpace(browser) && (browser.Trim().ToLower().Contains("ie") || browser.Trim().ToLower() == "internetexplorer"))
            {
                return HttpUtility.UrlEncode(fileName, Encoding.UTF8);
            }
            else
                return fileName;
            //string agent =HttpContext.Current.Request.Headers["USER-AGENT"];

            //if (!string.IsNullOrEmpty(agent) && agent.IndexOf("MSIE 6.0") != -1)
            //{
            //    string prefix = Path.GetFileNameWithoutExtension(fileName);

            //    string extension = Path.GetExtension(fileName);
            //    //UTF8 URL encoding only works in IE  
            //    fileName = HttpUtility.UrlEncode(StringHelper.SubStr(prefix, 13), Encoding.UTF8);
            //    // Encoded fileName cannot be more than 150  
            //    //int limit = 150 - extension.Length;
            //    //if (fileName.Length > limit)
            //    //{
            //    //    // because the UTF-8 encoding scheme uses 9 bytes to represent a single CJK character  
            //    //    fileName = HttpUtility.UrlEncode(prefix.Substring(0, Math.Min(prefix.Length, limit / 9)), Encoding.UTF8);

            //    //    fileName = fileName + extension;
            //    //}
            //    fileName = fileName + extension;
            //    return fileName;
            //}
            //else if (!string.IsNullOrEmpty(agent) && agent.IndexOf("MSIE") != -1)
            //{
            //    return HttpUtility.UrlEncode(fileName, Encoding.UTF8);
            //}
            //else if (!string.IsNullOrEmpty(agent) && agent.IndexOf("Mozilla") != -1)
            //{
            //    return fileName;
            //}
            //else
            //{
            //    return HttpUtility.UrlEncode(fileName, Encoding.UTF8);
            //}
        }
        #endregion
    }

    /// <summary>
    /// 图片大小 
    /// </summary>
    public class ImageSize
    {
        /// <summary>
        /// 宽
        /// </summary>
        public int Width { get; set; }
        /// <summary>
        /// 高
        /// </summary>
        public int Height { get; set; }

        public string GetFileName(string fileNameBefore, string fileExtension)
        {
            return fileNameBefore + "_" + Width + "_" + Height + fileExtension;
        }
    }
    /// <summary>
    /// 允许文件类型
    /// </summary>
    public enum UpFileType
    {
        image = 0,
        flash = 1,
        media = 2,
        file = 3,
    }
    /// <summary>
    /// 图片文件夹类型
    /// </summary>
    public enum ImageFolderType
    {
        /// <summary>
        /// 用户
        /// </summary>
        User = 0,
        /// <summary>
        /// 新闻
        /// </summary>
        News = 1,
        /// <summary>
        /// 项目
        /// </summary> 
        Project = 2,
        /// <summary>
        /// 临时目录
        /// </summary>
        Temp = 3,
        /// <summary>
        /// 其他
        /// </summary>
        Other = 4,
        /// <summary>
        /// 文本编辑器
        /// </summary>
        HtmlEditor = 5,

    }
}
